package work.chubanshe;

import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Set;

import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import work.utils.StandardUtils;

import com.h819.core.commons.Configurations;
import com.h819.core.commons.MyLangUtils;
import com.h819.core.db.MyDbUtils;
import com.h819.core.file.excel.poi.POIUtils;
import com.h819.core.utils.MyDateUtils;

/**
 * 本类用来处理由标准出版社《国家标准代替废止目录 2010》一书，
 * 
 * @ClassName: BookManage
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author h819
 * @date 2012-2-9 下午03:06:32
 * @version V1.0
 */

//

// 在运行的时候，一定要在 plsql 工具中，把 oracle 的视图、序列和触发器打开，查看其是否可以工作。

// 如果改变了表结构，会使视图或者触发器无法工作，需要再次编译一下，否则就不会触发 gateway 工作，就不会同步新插入的和更新的数据到 trs 数据库中。

// 先测试几条数据，查看 gateway 工作情况，正常之后，再大面积插入

public class BookManage {

	private Logger log = Logger.getLogger(BookManage.class);
	PropertiesConfiguration conf = Configurations
			.getInstance("work.properties");
	private QueryRunner runner = new QueryRunner();
	private Connection conn = MyDbUtils.getInstance("work.properties")
			.getConnection("oracle.jdbc.driver.OracleDriver",
					conf.getString("jdbc.oracle.work.235.url"),
					conf.getString("jdbc.oracle.work.235.user"),
					conf.getString("jdbc.oracle.work.235.password"));

	private final String bookName = "《国家标准代替废止目录 2010》";
	private final String bfdt = "部分代替";

	/**
	 * 执行之前首先执行 checkDTStandardCode 方法进行格式验证
	 * 
	 * 处理被代替标准目录 ， 该方法和 checkDTStandardCode 方法相同
	 * 
	 * 在检查完标准号格式之后(运行 checkDTStandardCode 方法)，进行数据更新
	 * 
	 * POIUtils.readExcel 方法，读取单元格的时候，去掉了换行，在应用本方法的时候，临时注释掉去掉换行语句。
	 * 
	 * @param execelFile
	 */

	private void updateDTStandard(File execelFile) {

		Set<String> setTemp = POIUtils.readExcel(execelFile);

		String update = "";
		String update1 = "";
		String select2 = "";
		String select1 = "";

		// 计数器
		int n = 0;
		String stdcode = "";

		for (String lineValue : setTemp) {

			n++;

			// 被代替标准号
			String stdCodeValue = POIUtils.getColumValue(lineValue, 0);
			// 历次修订，换行符分隔
			String stdHistoryCodeValue = POIUtils.getColumValue(lineValue, 1);
			// 现行标准号
			String stdNewCodeValue = POIUtils.getColumValue(lineValue, 2);

			/*
			 * POIUtils.readExcel 方法，读取单元格的时候，去掉了换行，在应用本方法的时候，临时
			 * 
			 * 注释掉换行语句。
			 */
			String[] stdh = StringUtils.split(stdHistoryCodeValue,
					MyLangUtils.linebreak);

			try {

				// 被代替标准号有“部分代替”字样的
				if (StringUtils.contains(stdCodeValue, bfdt)) {

					String[] stdh2 = StringUtils.split(stdCodeValue,
							MyLangUtils.linebreak);

					stdcode = stdh2[1] + "(" + bfdt + ")";

				} else
					stdcode = stdCodeValue;

				// 更新最新标准的被代替标准号为历史记录的第一条标准，即第一列的值
				if (stdNewCodeValue != null && !stdNewCodeValue.equals("")) {

					select1 = "select remark from st_standard where standard_code ='"
							+ stdNewCodeValue + "'";

					// log.info(select1);

					Object[] select1Result = runner.query(conn, select1,
							new ArrayHandler());

					// 标准号存在
					if (select1Result != null && select1Result.length != 0) {

						String strTemp = (String) select1Result[0];

						// 已经写过备注
						if (strTemp != null
								&& StringUtils.contains(strTemp, bookName)) {

							update1 = "update st_standard set replaced_standard ='"
									+ stdcode
									+ "',lasted_modify_time = sysdate where standard_code ='"
									+ stdNewCodeValue + "'";

						} else {

							update1 = "update st_standard set replaced_standard ='"
									+ stdcode
									+ "',remark = remark || ';(根据"
									+ bookName
									+ "一书更新)',lasted_modify_time = sysdate where standard_code ='"
									+ stdNewCodeValue + "'";
						}

						// 更新语句

						log.info("更新最新记录的被代替标准号：" + update1);
						runner.update(conn, update1);

					}

				}

				// String s1 = "";

				// 更新所有的历史记录的代替标准号为最新的，被代替标准号不做改动
				for (String s : stdh) {

					s = MyLangUtils.trim(s);
					// log.info("s : " + s);
					if (s != null && !s.equals("")) {

						// 都是国标。是否标准性质标注错误，不论错否，都标注为被代替状态
						select2 = "select remark from st_standard where standard_code ='"
								+ s
								+ "' or standard_code ='"
								+ StandardUtils.getReverseTypeStandardCode(s)
								+ "'";

						// log.info(select2);

						Object[] select1Result = runner.query(conn, select2,
								new ArrayHandler());

						// 标准号存在
						if (select1Result != null && select1Result.length != 0) {

							String remarkVlaue = (String) select1Result[0];

							// 已经写过备注
							if (remarkVlaue != null
									&& StringUtils.contains(remarkVlaue,
											bookName)) {

								update = "update st_standard set replace_standard ='"
										+ stdNewCodeValue
										+ "',lasted_modify_time = sysdate  where standard_code ='"
										+ s
										+ "' or standard_code ='"
										+ StandardUtils
												.getReverseTypeStandardCode(s)
										+ "'";

							} else {

								update = "update st_standard set replace_standard ='"
										+ stdNewCodeValue
										+ "',remark = remark || ';(根据"
										+ bookName
										+ "一书更新)',lasted_modify_time = sysdate  where standard_code ='"
										+ s
										+ "' or standard_code ='"
										+ StandardUtils
												.getReverseTypeStandardCode(s)
										+ "'";
							}

							// 更新语句
							log.info("更新历史记录的代替标准号：" + update);

							runner.update(conn, update);

						}

					}
				}

				// System.out.println(StringUtils.center(" 分隔符 ", 80, "==="));

			} catch (SQLException e) {
				// TODO Auto-generated catch block
				log.error(update1);
				log.error(update);
				log.error(select1);
				log.error(select2);
				e.printStackTrace();
				DbUtils.closeQuietly(conn);
				break;
			}

		}

		DbUtils.closeQuietly(conn);

	}

	/**
	 * 处理被代替标准目录
	 * 
	 * 检查标准号格式，如果有错误，手工更正后再继续进行
	 * 
	 * POIUtils.readExcel 方法，读取单元格的时候，去掉了换行，在应用本方法的时候，临时注释掉去掉换行语句。
	 * 
	 * @param execelFile
	 */

	private void checkDTStandardCode(File execelFile) {

		Set<String> setTemp = POIUtils.readExcel(execelFile);

		int n = 0;
		for (String lineValue : setTemp) {
			n++;

			// 去掉乱码，最主要的就这几个
			// lineValue = StringUtils.remove(lineValue, "癈");
			// lineValue = StringUtils.remove(lineValue, "癋");
			//
			// lineValue = StringUtils.remove(lineValue, "?");
			// lineValue = StringUtils.remove(lineValue, "鈥");

			// 被代替标准号
			String stdCodeValue = POIUtils.getColumValue(lineValue, 0);
			// 历次修订，换行符分隔
			String stdHistoryCodeValue = POIUtils.getColumValue(lineValue, 1);
			// 现行标准号
			String stdNewCodeValue = POIUtils.getColumValue(lineValue, 2);

			// log.info("stdCodeValue : " + stdCodeValue);
			// log.info("stdNewCodeValue : " + stdNewCodeValue);
			// log.info("stdHistoryCodeValue : " + stdHistoryCodeValue);

			/*
			 * POIUtils.readExcel 方法，读取单元格的时候，去掉了换行，在应用本方法的时候，临时
			 * 
			 * 注释掉去掉换行语句。
			 */
			String[] stdh = StringUtils.split(stdHistoryCodeValue,
					MyLangUtils.linebreak);

			// log.info("stdh : " + stdh.length);

			// System.out.println("stdCodeValue : " + stdCodeValue);
			// System.out.println("stdNewCodeValue : " + stdNewCodeValue);

			if (stdCodeValue.equals("") || stdNewCodeValue.equals("")) {
				log.info("第 " + n + " 行存在问题  " + stdCodeValue + ";  "
						+ stdNewCodeValue);
			}

			if (StringUtils.contains(stdCodeValue, bfdt)) {

				String[] stdh2 = StringUtils.split(stdCodeValue,
						MyLangUtils.linebreak);

				// String temp = StringUtils.substringAfter(stdCodeValue,
				// MyLangUtils.linebreak);

				// log.info("temp :"+stdh2[1]);

				if (!StandardUtils.isGBStandardCode(stdh2[1])) {
					log.info("第 " + n + " 行存在问题  stdCodeValue : "
							+ stdCodeValue + "  不满足标准号要求");
				}

			}

			if (!StandardUtils.isGBStandardCode(stdNewCodeValue)) {
				log.info("第 " + n + " 行存在问题  stdNewCodeValue : "
						+ stdNewCodeValue + "  不满足标准号要求");
			}

			for (String s : stdh) {
				// log.info("s : " + s);

				s = MyLangUtils.trim(s);

				if (!StandardUtils.isGBStandardCode(s)) {
					log.info("第 " + n + " 行存在问题  " + s + "  不满足标准号要求");
				}

			}

			// System.out.println(StringUtils.center(" 分隔符 ", 80,"==="));

			// StandardUtils.isGNStandardCode("");

		}
	}

	/**
	 * 执行之前首先执行 checkGBtoHBStandardCode 方法进行格式验证
	 * 
	 * 处理国标转化为行标标准目录， 该方法和 checkGBtoHBStandardCode 方法相同
	 * 
	 * 检查标准号格式，如果有错误，手工更正后再继续进行
	 * 
	 * POIUtils.readExcel 方法，读取单元格的时候，去掉了换行，在应用本方法的时候，临时注释掉去掉换行语句。
	 * 
	 * @param execelFile
	 */

	private void updateGBtoHBStandard(File execelFile) {

		Set<String> setTemp = POIUtils.readExcel(execelFile);

		int n = 0;
		for (String lineValue : setTemp) {

			String selectSql = "";
			String updateSql = "";
			String remarkValue = "";
			String remarkSql = "";
			String year = "";

			n++;

			try {

				// 被代替的国标标准号
				String stdCodeValue = POIUtils.getColumValue(lineValue, 0);

				// 现行行标标准号
				String stdNewCodeValue = POIUtils.getColumValue(lineValue, 1);

				if (StringUtils.contains(stdNewCodeValue, "(")) {

					String code = StringUtils.substringBefore(stdNewCodeValue,
							"(");
					year = StringUtils.substringBetween(stdNewCodeValue, "(",
							")");

					stdNewCodeValue = code;
				}

				/**
				 * 
				 * 更新最新的标准号
				 * **/
				// 更新最新标准的被代替标准号为第一列的值
				selectSql = "select remark from st_standard where standard_code ='"
						+ stdNewCodeValue + "'";

				log.info(selectSql);

				Object[] select1Result = runner.query(conn, selectSql,
						new ArrayHandler());

				// 标准号存在
				if (select1Result != null && select1Result.length != 0) {

					remarkValue = (String) select1Result[0];

					// 已经写过备注
					if (remarkValue != null
							&& StringUtils.contains(remarkValue, bookName)) {

						// log.info("year :" + year);
						// log.info("remark :" + remarkValue);

						if (!year.equals("")) {// 没写过确认年度
							if (!remarkValue.contains(year + "年确认有效"))

								remarkSql = ",remark = remark || ';(根据"
										+ bookName + "一书更新," + year + "年确认有效)'";
							else
								remarkSql = " ";

						}

						else
							remarkSql = " ";
					} else {

						if (!year.equals("")) {

							remarkSql = ",remark = remark || ';(根据" + bookName
									+ "一书更新," + year + "年确认有效)'";
						} else
							remarkSql = ",remark = remark || ';(根据" + bookName
									+ "一书更新" + ")'";

					}

					updateSql = "update st_standard set replaced_standard ='"
							+ stdCodeValue + "',lasted_modify_time = sysdate"
							+ remarkSql + " where standard_code ='"
							+ stdNewCodeValue + "'";

					log.info("最新记录的被代替标准号更新为旧的标准号：" + updateSql);

					runner.update(conn, updateSql);

				}

				/**
				 * 
				 * 更新旧的的标准号
				 * 
				 * **/

				// 更新旧的标准的代替标准号为第二列的值
				selectSql = "select remark from st_standard where standard_code ='"
						+ stdCodeValue
						+ "' or standard_code ='"
						+ StandardUtils
								.getReverseTypeStandardCode(stdCodeValue) + "'";

				log.info(selectSql);

				Object[] select2Result = runner.query(conn, selectSql,
						new ArrayHandler());

				// 标准号存在
				if (select2Result != null && select2Result.length != 0) {

					remarkValue = (String) select2Result[0];

					// 没写过备注
					if (remarkValue != null
							&& !StringUtils.contains(remarkValue, bookName)) {

						remarkSql = ",remark = remark || ';(根据" + bookName
								+ "一书更新)'";

					} else
						remarkSql = " ";

					updateSql = "update st_standard set replace_standard ='"
							+ stdNewCodeValue
							+ "',lasted_modify_time = sysdate "
							+ remarkSql
							+ " where standard_code ='"
							+ stdCodeValue
							+ "' or standard_code ='"
							+ StandardUtils
									.getReverseTypeStandardCode(stdCodeValue)
							+ "'";

					log.info("旧记录的代替标准号更新为新的标准号：" + updateSql);

					runner.update(conn, updateSql);

				}

			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// System.out.println(StringUtils.center(" 分隔符 ", 80, "==="));

		}
	}

	/**
	 * 处理国标转化为行标标准目录
	 * 
	 * 检查标准号格式，如果有错误，手工更正后再继续进行
	 * 
	 * POIUtils.readExcel 方法，读取单元格的时候，去掉了换行，在应用本方法的时候，临时注释掉去掉换行语句。
	 * 
	 * @param execelFile
	 */

	private void checkGBtoHBStandardCode(File execelFile) {

		Set<String> setTemp = POIUtils.readExcel(execelFile);

		int n = 0;
		for (String lineValue : setTemp) {
			n++;

			// 被代替的国标标准号
			String stdCodeValue = POIUtils.getColumValue(lineValue, 0);
			// log.info(stdCodeValue);
			// 现行行标标准号
			String stdNewCodeValue = POIUtils.getColumValue(lineValue, 1);

			if (stdCodeValue.equals("") || stdNewCodeValue.equals("")) {
				log.info("第 " + n + " 行存在问题  " + stdCodeValue + ";  "
						+ stdNewCodeValue);
				continue;
			}

			if (StringUtils.contains(stdNewCodeValue, "(")) {

				String code = StringUtils.substringBefore(stdNewCodeValue, "(");
				String year = StringUtils.substringBetween(stdNewCodeValue,
						"(", ")");

				stdNewCodeValue = code;

				// log.info("有确认年号：" + code + " ," + year);

				if (!year.matches(MyDateUtils.yearPatternReg)) {
					log.info("确认年代号格式错误  , (" + year + ")");
				}
			}

			if (!StandardUtils.isGNStandardCode(stdNewCodeValue)) {
				log.info("第 " + n + " 行存在问题  stdNewCodeValue : "
						+ stdNewCodeValue + "  不满足标准号要求");
			}

			if (!StandardUtils.isGNStandardCode(stdCodeValue)) {
				log.info("第 " + n + " 行存在问题  stdCodeValue : " + stdCodeValue
						+ "  不满足标准号要求");
			}

			System.out.println(StringUtils.center(" 分隔符 ", 80, "==="));

		}
	}

	/**
	 * 处理国标废止目录
	 * 
	 * 检查标准号格式，如果有错误，手工更正后再继续进行
	 * 
	 * POIUtils.readExcel 方法，读取单元格的时候，去掉了换行，在应用本方法的时候，临时注释掉去掉换行语句。
	 * 
	 * @param execelFile
	 */

	private void updateFZStandard(File execelFile) {

		Set<String> setTemp = POIUtils.readExcel(execelFile);

		int n = 0;
		for (String lineValue : setTemp) {

			n++;

			String updateSql = "";
			String selectSql = "";
			String remarkValue = "";
			String remarkSql = "";

			// 被代替的国标标准号
			String stdCodeValue = POIUtils.getColumValue(lineValue, 0);

			try {

				/**
				 * 
				 * 检查标准号是否存在
				 * **/
				// 更新最新标准的被代替标准号为第一列的值
				selectSql = "select remark from st_standard where standard_code ='"
						+ stdCodeValue
						+ "' or standard_code ='"
						+ StandardUtils
								.getReverseTypeStandardCode(stdCodeValue) + "'";

				log.info(selectSql);

				Object[] select1Result = runner.query(conn, selectSql,
						new ArrayHandler());

				if (select1Result == null || select1Result.length == 0) {
					log.info(stdCodeValue
							+ " 或 "
							+ StandardUtils
									.getReverseTypeStandardCode(stdCodeValue)
							+ " 不存在");
					continue;
				}

				remarkValue = (String) select1Result[0];

				// 已经写过备注
				if (remarkValue != null
						&& StringUtils.contains(remarkValue, bookName)) {
					remarkSql = " ";

				}

				else
					remarkSql = ",remark = remark || ';(根据" + bookName + "一书更新"
							+ ")'";

				updateSql = "update st_standard set status ='FZ',lasted_modify_time = sysdate"
						+ remarkSql
						+ " where standard_code ='"
						+ stdCodeValue
						+ "' or standard_code ='"
						+ StandardUtils
								.getReverseTypeStandardCode(stdCodeValue) + "'";

				log.info("更新状态为废止的语句是：：" + updateSql);

				runner.update(conn, updateSql);

			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			// System.out.println(StringUtils.center(" 分隔符 ", 80, "==="));

		}

		log.info("总计更新数据 ：" + n);
	}

	/**
	 * 处理国标废止目录
	 * 
	 * 检查标准号格式，如果有错误，手工更正后再继续进行
	 * 
	 * POIUtils.readExcel 方法，读取单元格的时候，去掉了换行，在应用本方法的时候，临时注释掉去掉换行语句。
	 * 
	 * @param execelFile
	 */

	private void checkFZStandardCode(File execelFile) {

		Set<String> setTemp = POIUtils.readExcel(execelFile);

		int n = 0;
		for (String lineValue : setTemp) {
			n++;

			// 被代替的国标标准号
			String stdCodeValue = POIUtils.getColumValue(lineValue, 0);

			if (stdCodeValue.equals("")) {
				log.info("第 " + n + " 行存在问题  " + stdCodeValue);
				continue;
			}

			if (!StandardUtils.isGNStandardCode(stdCodeValue)) {
				log.info("第 " + n + " 行存在问题  stdCodeValue : " + stdCodeValue
						+ "  不满足标准号要求");
			}

			// System.out.println(StringUtils.center(" 分隔符 ", 80, "==="));

		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		BookManage bm = new BookManage();

		// 在运行的时候，一定要在 plsql 工具中，把 oracle 的视图、序列和触发器打开，查看其是否可以工作。

		// 如果改变了表结构，会使视图或者触发器无法工作，需要再次编译一下，否则就不会触发 gateway 工作，就不会同步新插入的和更新的数据到
		// trs 数据库中。

		// 先测试几条数据，查看 gateway 工作情况，正常之后，再大面积插入

		// 计算执行时间
		long startTime = System.currentTimeMillis(); // 获取开始时间

		// 步骤零:
		// 先关闭 gateway，执行完毕后，再开启 gateway 同一执行

		/**
		 * 被代替标准数据导入
		 **/

		// 步骤一: 检查被代替标准号是否合法
		// bm.checkDTStandardCode(new File("d:\\01.xls"));
		// 步骤二: 更新被代替标准
		// bm.updateDTStandard(new File("d:\\01.xls"));

		/**
		 * 国标转化为行标标准目录
		 **/
		// 步骤一: 检查标准号是否合法
		// bm.checkGBtoHBStandardCode(new File("d:\\02.xls"));
		// 步骤二: 更新被代替标准
		// bm.updateGBtoHBStandard(new File("d:\\02.xls"));

		/**
		 * 废止国标目录
		 **/
		// 步骤一: 检查标准号是否合法
		// bm.checkFZStandardCode(new File("d:\\03.xls"));
		// 步骤二: 更新被代替标准
		// bm.updateFZStandard(new File("d:\\03.xls"));

		long endTime = System.currentTimeMillis(); // 获取结束时间

		System.out.println("程序运行时间： " + (endTime - startTime) / 1000 + "s");

	}
}